Repository navigation
Fixes #279 - #280
Merged
Merged
Fixes #279#280
Conversation
…ers (#279) Section 4.6 keys a re-confirmation by ID (old ID, new ID, date), never by folder, so the Yes, remove of one folder recorded every channel ID it held and that record accepted any other change of the same ID: a saved header name lost in a folder that is still there was published without being shown. reconfirmations() now leaves a channel open when, besides what the answers touch, it lost a position in a unit no answer names (a move: its own click, #258) or lost a header name while a folder still there no longer gives a saved name at the channel's position (reconcile records that per unit as headers_changed). Publication then refuses R_CONFIRMED_ID_CHANGED, and the line beside Save names the channel and the folder. A header name held only by the removed folder stays the removal's. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
…lder (#279) The lost positions were compared under the published folder names and every unit a rename touched was then set aside as answered, so channels re-ordered inside a renamed member folder were re-confirmed by the rename unseen (the move list does not show them either). Positions are now compared after the renames, and only units the user confirmed removed lose theirs by the answer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
… states no names (#279) A unit whose rewritten header states no channel names at all (header_names None, not one empty name) was skipped, so a removal elsewhere still accepted the saved name that folder lost, unseen. Such a header gives no saved name and now counts like an empty name: the ID stays refused with its reason beside Save. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01G3qp9AxjpGPw9xfWAUJNqc
Contributor
Author
Independent review of a50cc93, with two fixes pushed (now 9a8a25e)Reproduced from a fresh clone
Adversarial paths tried (notebook unless noted)
Fixed: one commit each, and each regression test fails before its fix
Gate on 9a8a25e: ruff passed, 437 files formatted, 5292 passed, 4 skipped (the same 4 environment skips), code rules passed. Spec modules: For the owner. Not fixed, because they are design limits rather than small defects.
Generated by Claude Code |
This was referenced Nov 11, 2026
A lost header name has no confirmation path: a later re-tag of that channel is refused for good
#281
Closed
Merged
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #279. Base:
mainb6f821a (the merge of #278). One commit: a50cc93.Summary
A §4.6 re-confirmation names an ID:
(id_kind, old_id, new_id, confirmed_on, both SHA-256). It does not name a folder. So Yes, remove of one folder recorded every channel ID that folder held, and that record accepted any change of those IDs. That included a saved header name lost in another folder that is still there, which the user never saw.description_removal.reconfirmations: a removal or rename answer now accepts a channel ID only when the channel has no other loss. A channel stays inopen(publication refuses it asR_CONFIRMED_ID_CHANGED) when, besides what the answers touch, either of these holds:The folders and what was lost are returned in the new
Reconfirmations.unseen.description_reconcile: each unit still in the folder carriesheaders_changed, the saved channels whose header name at their saved position is not a saved one. It uses the same comparison as_channels_differ, except that an empty name also counts when the channel has saved names.Notebook (Check and save): the line beside the disabled Save button names the channel and the folder, for example: "DNA lost a saved header name in ctrl/rep1, which is still there: a removal or rename does not confirm it (undo that tag on Channels)". The red
R_CONFIRMED_ID_CHANGED at channels.DNAmessage above the button is unchanged. Nothing is confirmed for the user.A header name held only by the removed folder is still covered by the removal: every folder still there gives a saved name.
Spec interpretation
reconfirmationbyid_kind,old_idandnew_id. The key set is fixed (RF4), and there is no folder or field key. So a channel with an unanswered change in a folder still there gets no record from the removal, and publication refuses it withR_CONFIRMED_ID_CHANGED(§4.6 (c)). I chose this safe side.describe: it does not share this logic. It holds no answers, so it never builds removal or rename re-confirmations (--publishrefuses every draft built from the folders), and nothing changes there.Evidence
Regression test
tests/test_reconfirm_scope.py::test_a_removal_does_not_accept_a_header_name_lost_in_a_folder_still_there[other-name|no-name]. Both cases fail on main (run against main'ssrc) and pass here. The scenario:Save is now disabled,
save_experiment()refuses, the reason shows beside the button, and no record is written. On main it published with a DNAreconfirmationfrom the removal.Guards, which pass on main and here:
Fixes #258, fixes #252 #278's tests all pass, including
test_a_removal_elsewhere_does_not_confirm_a_move.Byte-identical publishes, main vs this branch: the SHA-256 of
morphobricks.toml,experiment_design.csvandmorphobricks.records.jsonlis identical in five scenarios:header_names;Records files: the files written in those scenarios and by the new tests were checked with the Spec's
tools/audit/refrecords.py check(MorphoBricks-Spec main b4b1008). All pass: "2 records OK" and "7 records OK" (×4).Spec:
tests/spec_fixtures/andtests/test_spec_*.pyare untouched. 1732 passed, 0 skipped.Tests
python tools/check.pyon a50cc93 passed:ruff check: all checks passed;ruff format --check: 437 files already formatted;The 4 skips are environment-only:
test_cli_log.py:166,test_folder_rules.py:199andtest_folder_rules.py:230: "this file system tells names apart by case";test_discovery.py:665: "running with permissions that ignore file modes".The widgets were tested headless only. They were not looked at in JupyterLab or Colab.
Generated by Claude Code